package com.margo.project.consumer.rabbit.configuration;

import java.util.HashMap;
import java.util.Map;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 消息确认
 * 消息的确认，是指生产者投递消息后，如果Broker收到消息，则会给我们生产这一个应答。
 * 生产者进行接收应答，用来确定这条消息是否正常的发送到Broker，这种方式也是消息的可靠性投递的核心保障。
 * 第一步：在channel上开启确认模式：channel.confirmSelect()
 * 第二步：在channel上添加监听：addConfirmListener，监听成功和失败的返回结果，根据具体的结果对消息进行重新发送、或者记录日志等后续处理。
 * 
 * return消息机制
 * Return Listener用于处理一些不可路由的消息。我们的消息生产者，通过指定一个Exchange和Routingkey，把消息送到某一个队列中，
 * 然后我们的消费者监听队列，进行消息处理操作。
 * 但是在某些情况下，如果我们在发送消息的时候，当前的exchange不存在或者指定的路由key路由不到，
 * 这个时候我们需要监听这种不可达的消息，就要使用return listener。
 * 在基础API中有一个关键的配置项：
 * Mandatory：如果为true，则监听会接收到路由不可达的消息，然后进行后续处理，
 * 如果为false，那么broker端自动删除该消息。（默认false）
 * 
 * @author fxb208
 *
 */
@Configuration
@EnableRabbit
public class RabbitConsumerConfiguration {
	@Bean
	public MessageConverter messageConverter() {
		return new Jackson2JsonMessageConverter();
	}
	
	
	/**
	 * 死信队列
	 * https://blog.csdn.net/zhangcongyi420/article/details/100126666
	 * 进入死信队列
	 * 	消息被拒绝（basic.reject或basic.nack）并且requeue=false.
	 * 	消息TTL过期
	 * 	队列达到最大长度（队列满了，无法再添加数据到mq中）
	 * 
	 * https://blog.csdn.net/qq_42606051/article/details/83505233
	 */
	@Bean
	public Queue margoRabbitQueue() {
		Map<String, Object> arguments=new HashMap<String, Object>();
		arguments.put("x-dead-letter-exchange", "deadExchange");
		arguments.put("x-dead-letter-queue", "deadQueue");
		arguments.put("x-dead-letter-routing-key", "deadQueue");
		//arguments.put("x-message-ttl" , 15*1000);
		return QueueBuilder.durable("margoRabbitQueue").withArguments(arguments).build();
	}
	
	/**
	 * 正常交换器
	 * @return
	 */
	@Bean
	public TopicExchange margoRabbitExchange() {
		return new TopicExchange("margoRabbitExchange");
	}
	
	/**
	 * 绑定
	 * @return
	 */
	@Bean
	public Binding margoRabbitBinding() {
		return new Binding("margoRabbitQueue", Binding.DestinationType.QUEUE, "margoRabbitExchange", "margoRabbit", null);
	}
	
	/**
	 * 死信交换器
	 * @return
	 */
	@Bean
	public DirectExchange deadExchange() {
		return new DirectExchange("deadExchange");
	}

	/**
	 * 死信队列
	 * @return
	 */
	@Bean
	public Queue deadQueue() {
		return new Queue("deadQueue");
	}
	
	@Bean
	public Binding margoRabbitDeadBinding() {
		return new Binding("deadQueue", Binding.DestinationType.QUEUE, "deadExchange", "deadQueue", null);
	}
}
